﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using KKSGameLibrary.Logic;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using System.Collections.ObjectModel;
using KaKaSongGame.ViewModel;
using OnlineGameLibrary.Contract;
using System.Linq;
using KaKaSongGame.CtrlEx;

namespace KaKaSongGame
{
	public partial class CastleMap : UserControl, IPlayerActionUI
	{
        const int CARD_SIZE = 100;
        const double HINT_OPACITY = 0.4;

		ICardPresenter _presenter;
		public CastleMap()
		{
			InitializeComponent();
			Loaded += new RoutedEventHandler(CastleMap_Loaded);
		}

		void CastleMap_Loaded(object sender, RoutedEventArgs e)
		{
			_presenter = new CardPresenter();

            mappanel.Height = CardMap.SIZE * CARD_SIZE;
            mappanel.Width = CardMap.SIZE * CARD_SIZE;

			Brush linebrush = new SolidColorBrush(Colors.Black);

			for (int i = 1; i < CardMap.SIZE; i++)
			{
				var verticalline = new Line
				{
					Y1 = 0,
					Y2 = mappanel.Height,
                    X1 = i * CARD_SIZE,
                    X2 = i * CARD_SIZE,
					Stroke = linebrush,
					StrokeThickness = 1,
					StrokeDashOffset = 5,
					StrokeDashArray = new DoubleCollection { 10, 90 },
					IsHitTestVisible = false,
					UseLayoutRounding=false,
					StrokeLineJoin=PenLineJoin.Bevel
				};
				Canvas.SetZIndex(verticalline, - 2);
				mappanel.Children.Add(verticalline);

				var horizontalline = new Line
				{
                    Y1 = i * CARD_SIZE,
                    Y2 = i * CARD_SIZE,
					X1 = 0,
					X2 = mappanel.Width,
					Stroke = linebrush,
					StrokeThickness = 1,
					StrokeDashOffset = 5,
					StrokeDashArray = new DoubleCollection { 10, 90 },
					IsHitTestVisible = false,
					UseLayoutRounding = false,
					StrokeLineJoin = PenLineJoin.Bevel
				};
				Canvas.SetZIndex(horizontalline, -2);
				mappanel.Children.Add(horizontalline);

                InitCardHint();
                InitPuppetHint();
			}

			MainPageVM = this.DataContext as MainPageViewModel;
			if (MainPageVM == null)
				throw new Exception("datacontext is not mainpageviewmodel type.");
			MainPageVM.CardMap.RegionCompleted += new EventHandler<RegionCompleteEventArgs>(CardMap_RegionCompleted);
			MainPageVM.CardMap.RegionMerged += new EventHandler<RegionMergeEventArgs>(CardMap_RegionMerged);

			MainPageVM.MapWindow.PropertyChanged += MapWindow_PropertyChanged;
			MainPageVM.PlayerActionUI = this;

			// update minimap
			UpdateMinimap();

			// update viewwindow
			MainPageVM.MapWindow.Width = sv1.ViewportWidth;
			MainPageVM.MapWindow.Height = sv1.ViewportHeight;

            // set bg music
            bgme.Source = new Uri(new Uri(MainPageVM.GameInfo.GameClientComponentUri), "rondo.wma");

		}

		void CardMap_RegionCompleted(object sender, RegionCompleteEventArgs e)
		{
			MyTimer.DelayExcute(TimeSpan.FromSeconds(1.1), delegate
			{
				foreach (var card in e.Region.Cards)
				{
					var cardview = FindCard(card.Row, card.Column);
					cardview.Highlight(1);
				}

                tingme.Position = TimeSpan.FromSeconds(0);
                tingme.Play();

				foreach(var pair in e.Result.ScoreList)
				{
					var puppet = pair.Key;
					if(puppet.Position!=null)
					{
						var pin = FindPin(puppet.Position.Row, puppet.Position.Column, puppet.Position.OpenDirection);

						var playercontainer = playerlistctl.GetPlayerContainer(puppet.Player.ID);
						var pins = playercontainer.FindName("pinsp") as Panel;

						mappanel.Children.Remove(pin);
						pins.Children.Insert(0, pin);
					}
				}

			});
		}

		void SetCardPosition(int row, int col, GameCard card)
		{
            Canvas.SetLeft(card, col * CARD_SIZE);
            Canvas.SetTop(card, row * CARD_SIZE);
			Canvas.SetZIndex(card, -1);
			mappanel.Children.Add(card);
		}

		GameCard FindCard(int row, int col)
		{
			return mappanel.Children.First(e => (
				e is GameCard &&
                Canvas.GetTop(e as GameCard) == row * CARD_SIZE &&
                Canvas.GetLeft(e as GameCard) == col * CARD_SIZE)) as GameCard;
		}

		void CardMap_RegionMerged(object sender, RegionMergeEventArgs e)
		{
			if (e.Result.RemovedPuppet != null)
			{
				var puppet = e.Result.RemovedPuppet;
				var pin = FindPin(puppet.Position.Row, puppet.Position.Column, puppet.Position.OpenDirection);

				var playercontainer = playerlistctl.GetPlayerContainer(puppet.Player.ID);
				var pins = playercontainer.FindName("pinsp") as Panel;

				mappanel.Children.Remove(pin);
				pins.Children.Insert(0, pin);
			}
		}

		Point GetPinOffset(OpenDirection dir)
		{
			Point offset = new Point();
			int halfcell = 50;
			int halfpin = 15;

			switch (dir)
			{
				case OpenDirection.Center:
					offset.X = halfcell - halfpin;
					offset.Y = halfcell - halfpin;
					break;
				case OpenDirection.Left:
					offset.X = 0;
					offset.Y = halfcell - halfpin;
					break;
				case OpenDirection.Top:
					offset.X = halfcell - halfpin;
					offset.Y = 0;
					break;
				case OpenDirection.Right:
					offset.X = halfcell * 2 - halfpin;
					offset.Y = halfcell - halfpin;
					break;
				case OpenDirection.Bottom:
					offset.X = halfcell - halfpin;
					offset.Y = halfcell * 2 - halfpin;
					break;
				default:
					throw new Exception("why would go here?");
			}

			return offset;
		}

		void SetPinPosition(int row,int col, OpenDirection dir, PlayerPin pin)
		{
			var offset = GetPinOffset(dir);
            Canvas.SetLeft(pin, col * CARD_SIZE + offset.X);
            Canvas.SetTop(pin, row * CARD_SIZE + offset.Y);
			Canvas.SetZIndex(pin, 1);
			mappanel.Children.Add(pin);
		}

		PlayerPin FindPin(int row, int col, OpenDirection dir)
		{
			var offset = GetPinOffset(dir);
			
			var pin = mappanel.Children.First(
				u => (u is PlayerPin) &&
                    Canvas.GetLeft(u as PlayerPin) == col * CARD_SIZE + offset.X &&
                    Canvas.GetTop(u as PlayerPin) == row * CARD_SIZE + offset.Y);
			return pin as PlayerPin;
		}

		public MainPageViewModel MainPageVM
		{
		   set;get;
		}

		void MapWindow_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			var myrect = sender as MyRect;
			if (e.PropertyName == "X")
				this.sv1.ScrollToHorizontalOffset(myrect.X);
			else if (e.PropertyName == "Y")
				this.sv1.ScrollToVerticalOffset(myrect.Y);
		}


		public void SetOwner(int row, int col,OpenDirection dir,GamePlayer player)
		{
            // play sound
            dropme.Position = TimeSpan.FromSeconds(0);
            dropme.Play();

			actiontimer.DeactiveTimer(true);

			var playercontainer = playerlistctl.GetPlayerContainer(player.ID);
			var pins = playercontainer.FindName("pinsp") as Panel;

			var ppin = pins.Children.FirstOrDefault() as PlayerPin;

			pins.Children.Remove(ppin);
			SetPinPosition(row, col, dir, ppin);

			UpdateMinimap();

			playerlistctl.SetOwner(row, col, dir, player);
		}

		public void SetCard(CardInMap cardim,GamePlayer player)
		{
            // play sound
            dropme.Position = TimeSpan.FromSeconds(0);
            dropme.Play();

			actiontimer.DeactiveTimer(false);

			//var view = _presenter.CreateCardView(cardim);
			//((GameCard)view).CanRotate = false;

			var playercontainer = playerlistctl.GetPlayerContainer(player.ID);
			var cardview = playercontainer.Children.First(e=>e is GameCard) as GameCard;
            cardview.Height = CARD_SIZE;
            cardview.Width = CARD_SIZE;
			cardview.CardData = cardim;

			playercontainer.Children.Remove(cardview);
			SetCardPosition(cardim.Row, cardim.Column, cardview);

			MyTimer.DelayExcute(TimeSpan.FromSeconds(1), delegate
			{
				ScrollCellToCenter(cardim.Row, cardim.Column);
			});

			UpdateMinimap();

			playerlistctl.SetCard(cardim, player);

			//Dispatcher.BeginInvoke(delegate
			//{

			//});

		}

		void ScrollCellToCenter(int row, int col)
		{
            double y = row * CARD_SIZE + CARD_SIZE/2 - sv1.ViewportHeight / 2;
			if (y < 0) y = 0;
			//sv1.ScrollToVerticalOffset(y);

            double x = col * CARD_SIZE + CARD_SIZE/2 - sv1.ViewportWidth / 2;
			if (x < 0) x = 0;

			sv1.ScrollToCenter(y, x, new Duration(TimeSpan.FromSeconds(1)));
			//sv1.ScrollToHorizontalOffset(x);

		   // sv1.ScrollIntoView(mapgrid,0,-300,new Duration(TimeSpan.FromSeconds(1)));

			//sv1.ScrollIntoView(mapgrid, -x, -y, new Duration(TimeSpan.FromSeconds(1)));
		}

		GameCard curcardui;
		Point actionobjectposition = new Point(160,50);
		public void SetCardCandidate(Card card,GamePlayer player)
		{
			if (player.ID == MainPageVM.PlayerMe.ID)
			{
                if (curcardui != null)
                {
                    actiontimer.DeactiveTimer(true);
                }

				curcardui = _presenter.CreateCardView(
					new CardInMap
					{
						Card = card
					}) as GameCard;
				curcardui.CanRotate = true;
				//curcardui.CacheMode = new BitmapCache();

				curcardui.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
				curcardui.VerticalAlignment = System.Windows.VerticalAlignment.Top;

				curcardui.MouseLeftButtonDown += (cardui_MouseLeftButtonDown);
				curcardui.MouseLeftButtonUp += (cardui_MouseLeftButtonUp);
				curcardui.MouseMove += (cardui_MouseMove);

				curcardui.Margin = new Thickness(actionobjectposition.X, actionobjectposition.Y, 0, 0);
				//var fb = new Microsoft.Expression.Interactivity.Layout.FluidMoveBehavior();
				//fb.Attach(curcardui);
				cardcandidategrid.Children.Add(curcardui);
				actiontimer.ActiveTimer(MainPageVM.ActionTimeout, delegate
				{
					isdrag = false;
					ismousedown = false;
					cardcandidategrid.Children.Remove(curcardui);
                    HideCardHint();
				});
			}

			playerlistctl.SetCardCandidate(card, player);
		}

		PlayerPin playerpuppet;
		public void SetPuppetCandidate(GamePlayer player)
		{
			if (player.ID == MainPageVM.PlayerMe.ID)
			{
				var myplayervm = MainPageVM.PlayerList.First(p => p.GamePlayer.ID == MainPageVM.PlayerMe.ID);

				playerpuppet = new PlayerPin();
				playerpuppet.Width = 30;
				playerpuppet.Height = 30;
				playerpuppet.PuppetColor = myplayervm.PlayerColor;

				playerpuppet.MouseLeftButtonDown += (playerpuppet_MouseLeftButtonDown);
				playerpuppet.MouseLeftButtonUp += (playerpuppet_MouseLeftButtonUp);
				playerpuppet.MouseMove += (playerpuppet_MouseMove);

				playerpuppet.Margin = new Thickness(actionobjectposition.X, actionobjectposition.Y, 0, 0);

				passbutton.Visibility = Visibility.Visible;

				cardcandidategrid.Children.Add(playerpuppet);
				actiontimer.ActiveTimer(MainPageVM.ActionTimeout, delegate
				{
					isdrag = false;
					ismousedown = false;
					cardcandidategrid.Children.Remove(playerpuppet);
					passbutton.Visibility = Visibility.Collapsed;
                    HidePuppetHint();
				});
			}
			playerlistctl.SetPuppetCandidate(player);
		}

		private void Pass_Click(object sender, RoutedEventArgs e)
		{
			MainPageVM.SetOwner(false,-1,-1,OpenDirection.Center);
			actiontimer.DeactiveTimer(true);
		}

		public const double MINIMAP_SCALE = 0.1;
		void UpdateMinimap()
		{
			Dispatcher.BeginInvoke(delegate
			{
				var matrix = new ScaleTransform
				{
					ScaleX = MINIMAP_SCALE,
					ScaleY = MINIMAP_SCALE
				};
				//mapgrid.ShowGridLines = false;
				WriteableBitmap minimap = new WriteableBitmap(mappanel, matrix);
				//mapgrid.ShowGridLines = true;

				MainPageVM.MiniMapImage = minimap;
			});
		}
		
		private void sv1_SizeChanged(object sender, SizeChangedEventArgs e)
		{
			if (this.MainPageVM != null)
			{
				MainPageVM.MapWindow.Width = sv1.ViewportWidth;
				MainPageVM.MapWindow.Height = sv1.ViewportHeight;
			}
		}

		bool isdrag;
		bool ismousedown;
		Point relativepos;

		Rectangle cardhintrect;
        private void InitCardHint()
        {
            cardhintrect = new Rectangle
            {
                Width = CARD_SIZE,
                Height = CARD_SIZE,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
            };
            cardhintrect.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(cardhintrect);
        }
        private void SetCardHint(CardInMap cardim)
        {
            cardhintrect.Visibility = System.Windows.Visibility.Visible;
            var result = MainPageVM.CardMap.TestSetCard(cardim);
            if (result)
            {
                cardhintrect.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                cardhintrect.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetTop(cardhintrect, cardim.Row * CARD_SIZE);
            Canvas.SetLeft(cardhintrect, cardim.Column * CARD_SIZE);
        }
        private void HideCardHint()
        {
            cardhintrect.Visibility = System.Windows.Visibility.Collapsed;
        }

		void cardui_MouseMove(object sender, MouseEventArgs e)
		{
			if (ismousedown)
			{
				isdrag = true;
				
				var curpos = e.GetPosition(cardcandidategrid);

				curcardui.Margin = new Thickness(
					curpos.X - relativepos.X,
					curpos.Y - relativepos.Y,
					0, 0);

				//var positon = e.GetPosition(mapgrid);
                //int col = (int)positon.X / CardSize;
                //int row = (int)positon.Y / CardSize;
				//if (MainPageVM.CardMap.TestSetCard(curcardui.CardData as CardInMap))
				//{
					
				//}
				//else
				//{

				//}
			}
            // show hint here
            if (isdrag)
            {
                var positon = e.GetPosition(mappanel);
                int col = (int)positon.X / CARD_SIZE;
                int row = (int)positon.Y / CARD_SIZE;

                var cardim = curcardui.CardData;
                cardim.Column = col;
                cardim.Row = row;

                SetCardHint(cardim);
            }
		}

		void SetRedRectangle(int row ,int col)
		{
			//if()
		}

		void cardui_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			if (isdrag)
			{
				isdrag = false;

                HideCardHint();

				var positon = e.GetPosition(mappanel);
                int col = (int)positon.X / CARD_SIZE;
                int row = (int)positon.Y / CARD_SIZE;

				var cardim = curcardui.CardData;
				cardim.Column = col;
				cardim.Row = row;

				if (MainPageVM.CardMap.TestSetCard(cardim))
				{
					// ui
					cardcandidategrid.Children.Remove(curcardui);
					curcardui.MouseLeftButtonDown -= (cardui_MouseLeftButtonDown);
					curcardui.MouseLeftButtonUp -= (cardui_MouseLeftButtonUp);
					curcardui.MouseMove -= (cardui_MouseMove);

					// server
					MainPageVM.SetCard(cardim);
				}
				else
				{
					curcardui.Margin = new Thickness(actionobjectposition.X, actionobjectposition.Y, 0, 0);
				}
				((FrameworkElement)sender).ReleaseMouseCapture();
			}
			e.Handled = false;
			ismousedown = false;
		}

		void cardui_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
            dragme.Position = TimeSpan.FromSeconds(0);
            dragme.Play();
			ismousedown = true;
			relativepos = e.GetPosition(sender as FrameworkElement);	
		}


		public void PlayerActionTimeout(GamePlayer player)
		{
			// show timeout
		}


        Rectangle puppethintrect_left;
        Rectangle puppethintrect_top;
        Rectangle puppethintrect_right;
        Rectangle puppethintrect_bottom;
        Rectangle puppethintrect_center;
        private void InitPuppetHint()
        {
            // left
            puppethintrect_left = new Rectangle
            {
                Width = CARD_SIZE / 3,
                Height = CARD_SIZE / 3,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
                RenderTransform = new TranslateTransform
                {
                    X = 0,
                    Y = CARD_SIZE / 3
                }
            };
            puppethintrect_left.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(puppethintrect_left);

            // top
            puppethintrect_top = new Rectangle
            {
                Width = CARD_SIZE / 3,
                Height = CARD_SIZE / 3,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
                RenderTransform = new TranslateTransform
                {
                    X = CARD_SIZE / 3,
                    Y = 0
                }
            };
            puppethintrect_top.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(puppethintrect_top);

            //right
            puppethintrect_right = new Rectangle
            {
                Width = CARD_SIZE / 3,
                Height = CARD_SIZE / 3,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
                RenderTransform = new TranslateTransform
                {
                    X = CARD_SIZE * 2 / 3,
                    Y = CARD_SIZE / 3
                }
            };
            puppethintrect_right.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(puppethintrect_right);

            // bottom
            puppethintrect_bottom = new Rectangle
            {
                Width = CARD_SIZE / 3,
                Height = CARD_SIZE / 3,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
                RenderTransform = new TranslateTransform
                {
                    X = CARD_SIZE / 3,
                    Y = CARD_SIZE * 2 / 3
                }
            };
            puppethintrect_bottom.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(puppethintrect_bottom);

            // center
            puppethintrect_center = new Rectangle
            {
                Width = CARD_SIZE / 3,
                Height = CARD_SIZE / 3,
                Fill = new SolidColorBrush(Colors.Red),
                Opacity = HINT_OPACITY,
                RenderTransform = new TranslateTransform
                {
                    X = CARD_SIZE / 3,
                    Y = CARD_SIZE / 3
                }
            };
            puppethintrect_center.Visibility = System.Windows.Visibility.Collapsed;
            mappanel.Children.Add(puppethintrect_center);

        }
        private void SetPuppetHint(int row, int col)
        {
            // left
            puppethintrect_left.Visibility = System.Windows.Visibility.Visible;
            if (MainPageVM.CardMap.TestSetOwner(row, col, OpenDirection.Left, MainPageVM.PlayerMe))
            {
                puppethintrect_left.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                puppethintrect_left.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetLeft(puppethintrect_left, CARD_SIZE * col);
            Canvas.SetTop(puppethintrect_left, CARD_SIZE * row);

            // top
            puppethintrect_top.Visibility = System.Windows.Visibility.Visible;
            if (MainPageVM.CardMap.TestSetOwner(row, col, OpenDirection.Top, MainPageVM.PlayerMe))
            {
                puppethintrect_top.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                puppethintrect_top.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetLeft(puppethintrect_top, CARD_SIZE * col);
            Canvas.SetTop(puppethintrect_top, CARD_SIZE * row);

            // right
            puppethintrect_right.Visibility = System.Windows.Visibility.Visible;
            if (MainPageVM.CardMap.TestSetOwner(row, col, OpenDirection.Right, MainPageVM.PlayerMe))
            {
                puppethintrect_right.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                puppethintrect_right.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetLeft(puppethintrect_right, CARD_SIZE * col);
            Canvas.SetTop(puppethintrect_right, CARD_SIZE * row);

            // bottom
            puppethintrect_bottom.Visibility = System.Windows.Visibility.Visible;
            if (MainPageVM.CardMap.TestSetOwner(row, col, OpenDirection.Bottom, MainPageVM.PlayerMe))
            {
                puppethintrect_bottom.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                puppethintrect_bottom.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetLeft(puppethintrect_bottom, CARD_SIZE * col);
            Canvas.SetTop(puppethintrect_bottom, CARD_SIZE * row);

            // center
            puppethintrect_center.Visibility = System.Windows.Visibility.Visible;
            if (MainPageVM.CardMap.TestSetOwner(row, col, OpenDirection.Center, MainPageVM.PlayerMe))
            {
                puppethintrect_center.Fill = new SolidColorBrush(Colors.Green);
            }
            else
            {
                puppethintrect_center.Fill = new SolidColorBrush(Colors.Red);
            }
            Canvas.SetLeft(puppethintrect_center, CARD_SIZE * col);
            Canvas.SetTop(puppethintrect_center, CARD_SIZE * row);

        }
        private void HidePuppetHint()
        {
            puppethintrect_left.Visibility = System.Windows.Visibility.Collapsed;
            puppethintrect_top.Visibility = System.Windows.Visibility.Collapsed;
            puppethintrect_right.Visibility = System.Windows.Visibility.Collapsed;
            puppethintrect_bottom.Visibility = System.Windows.Visibility.Collapsed;
            puppethintrect_center.Visibility = System.Windows.Visibility.Collapsed;
        }

		void playerpuppet_MouseMove(object sender, MouseEventArgs e)
		{
			if (ismousedown)
			{
				isdrag = true;
				Point curpos = e.GetPosition(cardcandidategrid);

				playerpuppet.Margin = new Thickness(
					curpos.X - relativepos.X,
					curpos.Y - relativepos.Y,
					0, 0);
			}
			//show hint here
            if (isdrag)
            {
                var positon = e.GetPosition(mappanel);
                int col = (int)positon.X / CARD_SIZE;
                int row = (int)positon.Y / CARD_SIZE;

                SetPuppetHint(row, col);
            }
        }

		void playerpuppet_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			if (isdrag)
			{
				isdrag = false;
                HidePuppetHint();

				var position = e.GetPosition(mappanel);

                int col = (int)position.X / CARD_SIZE;
                int row = (int)position.Y / CARD_SIZE;

                int xoffset = (int)position.X % CARD_SIZE;
                int yoffset = (int)position.Y % CARD_SIZE;
				OpenDirection dir = GetMouseDirection(xoffset, yoffset);

				var result = MainPageVM.CardMap.TestSetOwner(row, col, dir, MainPageVM.PlayerMe);

				if (result)
				{
					// ui
					cardcandidategrid.Children.Remove(playerpuppet);
					playerpuppet.MouseLeftButtonDown -= (playerpuppet_MouseLeftButtonDown);
					playerpuppet.MouseLeftButtonUp -= (playerpuppet_MouseLeftButtonUp);
					playerpuppet.MouseMove -= (playerpuppet_MouseMove);

					//server
					MainPageVM.SetOwner(true, row, col, dir);
				}
				else
				{
					playerpuppet.Margin = new Thickness(actionobjectposition.X, actionobjectposition.Y, 0, 0);
				}
			}
			ismousedown = false;
			((FrameworkElement)sender).ReleaseMouseCapture();
		}

		OpenDirection GetMouseDirection(int xoffset, int yoffset)
		{
            int col = xoffset * 3 / CARD_SIZE;
            int row = yoffset * 3 / CARD_SIZE;
			if (col == 0 && row == 1)
				return OpenDirection.Left;
			else if (col == 1 && row == 0)
				return OpenDirection.Top;
			else if (col == 1 && row == 1)
				return OpenDirection.Center;
			else if (col == 1 && row >= 2)
				return OpenDirection.Bottom;
			else if (col >= 2 && row == 1)
				return OpenDirection.Right;
			else
				return OpenDirection.Center;
		}

		void playerpuppet_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
            dragme.Position = TimeSpan.FromSeconds(0);
            dragme.Play();

			ismousedown = true;
			relativepos = e.GetPosition(sender as FrameworkElement);
			((FrameworkElement)sender).CaptureMouse();
		}

        // background music loop
        private void bgme_MediaEnded(object sender, RoutedEventArgs e)
        {
            bgme.Position = TimeSpan.FromSeconds(0);
            bgme.Play();
        }
	}
}